package com.espirit.common;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.mvel2.MVEL;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.espirit.eap.manager.I18n;
import com.espirit.eap.manager.workflow.WFInstance;
import com.espirit.eap.manager.workflow.WFInstanceService;
import com.espirit.eap.manager.workflow.WFPhase;
import com.espirit.eap.manager.workflow.WFTemplate;
import com.espirit.eap.manager.workflow.WorkflowAware;
import com.espirit.eap.sa.LoginUser;
import com.googlecode.cswish.annotation.GenericType;
import com.googlecode.cswish.annotation.ParamScope;
import com.googlecode.cswish.annotation.Rest;
import com.googlecode.cswish.exception.ApplicationException;
import com.googlecode.cswish.model.PageElements;
import com.googlecode.cswish.model.PageInfo;
import com.googlecode.cswish.model.ParameterMap;
import com.googlecode.cswish.model.Reference;
import com.googlecode.cswish.oosearch.QLInfo;
import com.googlecode.cswish.struts.conversion.PageElementService;
import com.googlecode.cswish.util.BlankObject;
import com.opensymphony.xwork2.Result;

@Service
public class WFMessageService extends MessageService{
	@Resource
	WFInstanceService instanceService;
	
	@Resource
	private PageElementService pageElementService;
	
//	@Rest(simpleServiceName="espirit.common.message", type="search")
	public  PageInfo search(ParameterMap model,
    		int start, int limit, String sort, String dir, boolean newSearch,
    		Reference<QLInfo> qlInfoRef){
		if (StringUtils.isEmpty(sort)){
			sort = "a.createdOn";
			dir = "desc";
		}
		if (newSearch ){
			model.setDisableAutoCreation(true);
			model.put("to.id", loginUserService.getLoginUser().getId());
			String statusType = model.getParameter("statusType", String.class);
			if (statusType == null){
				model.setParameter("statusType", WFMessage.STATUS_OPEN);
				statusType = WFMessage.STATUS_OPEN;
			}
			if (WFMessage.STATUS_OPEN.equals(statusType)){
				model.setParameter("hidden", false);
			} else if (WFMessage.STATUS_CLOSE.equals(statusType)){
				model.setParameter("hidden", true);
			}
		}
		
		return genericService.search(model, start, limit, sort, dir, newSearch, qlInfoRef);
	}
	
	@Rest(simpleServiceName="espirit.common.message", type="_update")
	public Result _update(@GenericType Object model,@ParamScope(visible=false, value="#ps")PageElements ps) {
    	if (model == null) return null;
    	WFMessage message = (WFMessage)genericService.load(model);
    	
		try {
			Class clazz = Class.forName(message.getInstance().getSrcClassName());
			
			/*
			 * FIXME: 
			if (Form.class.isAssignableFrom(clazz)){
	    		return urlUtil.getUrlResult(clazz, "_accept", "model.wfMessage.id="+ message.getId());
	    	}*/
			
	    	return urlUtil.getUrlResult(WFMessage.class, "_accept", "model.id="+ message.getId());
	    	
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	
    	
    	return null;
    }
	
	@Transactional
	@Rest(simpleServiceName="espirit.common.message", type="update")
	public void update(WFMessage model){
		Map<String, Object> action = new HashMap<String, Object>();
		action.put("model", model);
		instanceService.process(model, action);
	}

	@Rest(simpleServiceName="loginUser", type="free")
	public void _accept(@GenericType Object model,@ParamScope(visible=false, value="#ps")PageElements ps) {
    	if (model == null) return ;
    	WFMessage message = (WFMessage)genericService.load(model);
    	ognlExUtil.getOgnlUtil().copy(message, model, BlankObject.Map);

    	ps.setElementReadOnly("model.initDate", true);
    	ps.setElementVisible("model.instance.id", false);
    	ps.setElementVisible("model.instance.wfPhase.id", false);
    	ps.setElementVisible("model.instance.wfTemplate.id", false);
    	ps.setElementReadOnly("model.instance.description", true);
    	ps.setElementRequired("model.instance.status.id", true);
    }
	
	@Rest(simpleServiceName="loginUser", type="free")
	@Transactional
	public void accept(WFMessage model){
		Map<String, Object> action = new HashMap<String, Object>();
		action.put("model", model);
		instanceService.process(model, action);
	}
	
	public WFMessage getMyApprovingMessageByWorklowAware(WorkflowAware aware) {
		List<WFMessage> results = getWFMessagesByWorklowAware(aware, loginUserService.getLoginUser().getId() ,false);
		if (results != null && !results.isEmpty()){
			WFMessage result = results.get(0);
			return result;
		}
		return null;
	}
	
	public List<WFMessage> getWFMessagesByWorklowAware(WorkflowAware aware ,String userId ,Boolean hidden){
		WFMessage model = new WFMessage();
		WFInstance instance = new WFInstance();
		instance.onSetSrcClassName(aware);
		instance.setSrcId(aware.getId());
		if (userId != null){
			LoginUser to = new LoginUser();
			to.setId(userId);
			model.setTo(to);
		}
		if (hidden != null){
			model.setHidden(hidden);
		}
		
		model.setInstance(instance);
		return  genericService.searchAll(model).getData();
	}
	
	public List<WFMessage> getUnDealedWFMessagesByWorklowAwareAndPhase(WorkflowAware aware ,WFTemplate template, WFPhase phase){
		WFMessage model = new WFMessage();
		WFInstance instance = new WFInstance();
		instance.onSetSrcClassName(aware);
		instance.setSrcId(aware.getId());
		instance.setWfPhase(phase);
		instance.setWfTemplate(template);
		model.setHidden(false);
		
		model.setInstance(instance);
		return  genericService.searchAll(model).getData();
	}
	
	public List<Map<String,String>> getStatusType(){
		List<Map<String ,String>> results = new ArrayList<Map<String,String>>();

		Map<String ,String> types =  new HashMap<String , String>();
		types =  new HashMap<String , String>();
		types.put("id", "all");
		types.put("name", new I18n("Status.All", "All", "所有").getName());
		results.add(types);
		
		types =  new HashMap<String , String>();
		types.put("id", WFMessage.STATUS_OPEN);
		types.put("name", new I18n("Status.ToDo", "ToDO", "待办").getName());
		results.add(types);

		types =  new HashMap<String , String>();
		types.put("id", WFMessage.STATUS_CLOSE);
		types.put("name", new I18n("Status.Done", "Done", "已办").getName());
		results.add(types);

		return results;
	}
	
	
	public Result _approve(List results){
		if (results == null || results.size() == 0) return null;
		
		WorkflowAware workflowAware = null;
		for (Object item : results) {
			if (!(item instanceof WorkflowAware)) continue;
			workflowAware = (WorkflowAware) item;
			if (workflowAware == null || workflowAware.getId() == null) continue;
			workflowAware  = genericService.load(workflowAware.getClass(),workflowAware.getId());
			break;
		}
		WFMessage message = getMyApprovingMessageByWorklowAware(workflowAware);
		if (message == null){
			throw new ApplicationException("errors.workflow.accept.not.me",MVEL.getProperty(workflowAware.getSrcEntityKey(), workflowAware));
		}
		return urlUtil.getUrlResult(WFMessage.class, "_update", "model.id=" + message.getId());
	}
}
